#!/bin/sh


function log()
{
  if [ "${debug}" == "" ] ; then debug=0; fi
  if [ ${debug} -gt 0 ] ; then echo $1$2$3$4$5$6$7$8$9 >&2; fi;
}

function error()
{
    echo -e "\033[0;31mERROR($1)!\033[0m"
    exit $1;
}


function init_display()
{


    tip_a="环境要求："
    tip_b="当前环境："
    tip_ok="符合"
    tip_err="不符合"
    tip_ret="检测结果："
    tip_or=" 或 "
    tip_days="天"

    tip_do="开始${product}试用安装环境最低配置检测"
    tip_done="服务器适用性已检测完成"
    tip_result_err="当前服务器检查结果为\033[0;31m【不适用】\033[0m，请选择其它服务器！"
    #tip_result_ok="当前服务器检查结果为\033[0;32m【适用】\033[0m，检测结果文件已保存在${target}${product}_ENV.txt\n请将文件拷贝出来，在网站产品试用申请页面上传."
    tip_result_ok="当前服务器检查结果为\033[0;32m【适用】\033[0m。"
    tip_thx="谢谢您的配合！"




    tip_found="发现"
    tip_notfound="没有发现"

    tip_root="【多超级帐户】"
    tip_nopassword="【空口令帐户】"
    tip_pwd_max_lifetime="【口令最长使用期限】"
    tip_pwd_min_lifetime="【口令最小更改间隔】"
    tip_pwd_length="【口令长度】"
    tip_pwd_alert="【口令过期预警】"
    tip_path="【路径变量.】"



    myname=`basename "$0" .sh`



    mypath=`dirname "$0"`
    mypath="${mypath}/"







    env_version=BT_ENV_LINUX_20200105_1
    debug=0

}
function check_centos_root()
{
   root_uids=(`awk -F: '($3 == 0) { print $1 }' /etc/passwd | grep -Pv "root" | tr '\n' ' '`)
   root_count=${#root_uids[@]}
   if [ "${root_count}" == "" ] || [ "${root_count}" == "0" ]  ; then return 0; else return 1; fi
}

function check_centos_nopassword()
{
   nopassword=(`awk -F: '($2 == "") { print $1 }' /etc/shadow | tr '\n' ' '`)
   no_count=${#nopassword[@]}
   if [ "${no_count}" == "" ] || [ "${no_count}" == "0" ]  ; then return 0; else return 1; fi
}

function check_centos_pwd_max_lifetime()
{
   lifetime_max=`cat /etc/login.defs | grep -Po "^\s*PASS_MAX_DAYS\s*\K\d+"`
   if [ "${lifetime_max}" == "" ] ; then lifetime_max=99999; fi
   if [ "${bt_lifetime_max}" == "" ] ; then bt_lifetime_max=90; fi
   if [ ${lifetime_max} -gt ${bt_lifetime_max} ] ; then return 1; else return 0; fi
}

function check_centos_pwd_min_lifetime()
{
   lifetime_min=`cat /etc/login.defs | grep -Po "^\s*PASS_MIN_DAYS\s*\K\d+"`
   if [ "${lifetime_min}" == "" ] ; then lifetime_min=0; fi
   if [ "${bt_lifetime_min}" == "" ] ; then bt_lifetime_min=1; fi
   if [ ${lifetime_min} -ge ${bt_lifetime_min} ] ; then return 0; else return 1; fi
}


function check_centos_pwd_length()
{
   pwd_length=`cat /etc/login.defs | grep -Po "^\s*PASS_MIN_LEN\s*\K\d+"`
   if [ "${pwd_length}" == "" ] ; then pwd_length=0; fi
   if [ "${bt_pwd_length}" == "" ] ; then bt_pwd_length=8; fi
   if [ ${pwd_length} -ge ${bt_pwd_length} ] ; then return 0; else return 1; fi
}

function check_centos_pwd_alert()
{
   pwd_alert=`cat /etc/login.defs | grep -Po "^\s*PASS_WARN_AGE\s*\K\d+"`
   if [ "${pwd_alert}" == "" ] ; then pwd_alert=0; fi
   if [ "${bt_pwd_alert}" == "" ] ; then bt_pwd_alert=14; fi
   if [ ${pwd_alert} -ge ${bt_pwd_alert} ] ; then return 0; else return 1; fi
}

function check_centos_path()
{
   path_count=`echo $PATH |  grep -Po "(^|:)\s*\.\s*(:|$)" | wc -l`
   if [ ${path_count} -eq 0 ] ; then return 0; else return 1; fi
}





function check_security()
{
    has_error=0

        check_centos_root
        root_ret=$?

    log "check_root: " ${root_ret}
    if [ ${root_ret} -ne 0 ]
    then
        has_error=1
        echo -e "${tip_root}  ${tip_ret} \033[0;31m${tip_err}\033[0m"
        echo "  ${tip_b}${tip_found}(${root_uids[@]})"
    else
        echo -e "${tip_root}  ${tip_ret} \033[0;32m${tip_ok}\033[0m"
        echo "  ${tip_b}${tip_notfound}"
    fi



        check_centos_nopassword
        no_ret=$?

    log "check nopassword: " ${no_ret}
    if [ ${no_ret} -ne 0 ]
    then
        has_error=1
        echo -e "${tip_nopassword}  ${tip_ret} \033[0;31m${tip_err}\033[0m"
        echo "  ${tip_b}${tip_found}(${nopassword[@]})"
    else
        echo -e "${tip_nopassword}  ${tip_ret} \033[0;32m${tip_ok}\033[0m"
        echo "  ${tip_b}${tip_notfound}"
    fi



        check_centos_pwd_max_lifetime
        xlt_ret=$?

    log "check password max lifetime: " ${xlt_ret}
    if [ ${xlt_ret} -ne 0 ]
    then
        has_error=1
        echo -e "${tip_pwd_max_lifetime}  ${tip_ret} \033[0;31m${tip_err}\033[0m"
    else
        echo -e "${tip_pwd_max_lifetime}  ${tip_ret} \033[0;32m${tip_ok}\033[0m"
    fi
        echo "  ${tip_a}<${bt_lifetime_max}${tip_days}"
        echo "  ${tip_b}${lifetime_max}${tip_days}"

        check_centos_pwd_min_lifetime
        lt_ret=$?

    log "check password min lifetime: " ${lt_ret}
    if [ ${lt_ret} -ne 0 ]
    then
        has_error=1
        echo -e "${tip_pwd_min_lifetime}  ${tip_ret} \033[0;31m${tip_err}\033[0m"
    else
        echo -e "${tip_pwd_min_lifetime}  ${tip_ret} \033[0;32m${tip_ok}\033[0m"
    fi
        echo "  ${tip_a}>=${bt_lifetime_min}${tip_days}"
        echo "  ${tip_b}${lifetime_min}${tip_days}"



        check_centos_pwd_length
        len_ret=$?

    log "check password length: " ${len_ret}
    if [ ${len_ret} -ne 0 ]
    then
        has_error=1
        echo -e "${tip_pwd_length}  ${tip_ret} \033[0;31m${tip_err}\033[0m"
    else
        echo -e "${tip_pwd_length}  ${tip_ret} \033[0;32m${tip_ok}\033[0m"
    fi
        echo "  ${tip_a}>=${bt_pwd_length}"
        echo "  ${tip_b}${pwd_length}"




        check_centos_pwd_alert
        alert_ret=$?

    log "check password alert: " ${alert_ret}
    if [ ${alert_ret} -ne 0 ]
    then
        has_error=1
        echo -e "${tip_pwd_alert}  ${tip_ret} \033[0;31m${tip_err}\033[0m"
    else
        echo -e "${tip_pwd_alert}  ${tip_ret} \033[0;32m${tip_ok}\033[0m"
    fi
        echo "  ${tip_a}>=${bt_pwd_alert}"
        echo "  ${tip_b}${pwd_alert}"



       check_centos_path
       path_ret=$?

    log "check path: " ${path_ret}
    if [ ${path_ret} -ne 0 ]
    then
        has_error=1
        echo -e "${tip_path}  ${tip_ret} \033[0;31m${tip_err}\033[0m"
        echo "  ${tip_b}${tip_found}"
    else
        echo -e "${tip_path}  ${tip_ret} \033[0;32m${tip_ok}\033[0m"
        echo "  ${tip_b}${tip_notfound}"
    fi



}




function runner_root()
{
   if [ `whoami` != "root" ] ; then echo "必须使用root帐号运行！";exit 1; fi
}

function security_root_power()
{


   old_value=`ls -ld ~ | grep -Po "^.{10}"`
   if [ "${old_value}" != "drwx------" ]; then
      echo 增强root用户的home目录许可权限
      chmod 700 ~
      if [ $? -ne 0 ] ; then echo -e "操作\033[0;31m失败\033[0m"; fi
   fi 

   login_defs=/etc/login.defs
   old_value=`grep -Po "^\s*PASS_MIN_LEN\s+\K[0-9]+" ${login_defs}`
   if [ "${old_value}" == "" ] ; then
      echo 设置系统口令策略
      echo PASS_MIN_LEN   12>>${login_defs}
   else
       if [ "${old_value}" != "12" ]; then
          echo 增强系统口令策略
          \cp -f ${login_defs} ${login_defs}.bak
          sed 's/^\s*PASS_MIN_LEN\s\+.*/PASS_MIN_LEN   12/' ${login_defs}.bak >${login_defs}
       fi
   fi
   old_value=`grep -Po "^\s*PASS_MIN_LEN\s+\K[0-9]+" ${login_defs}`
   if  [ "${old_value}" == "" ] || [ "${old_value}" != "12" ]; then echo -e "操作\033[0;31m失败\033[0m";  fi

   su_files=/etc/pam.d/su
   old_value=`head -n 1 ${su_files}  | grep -P "auth\s*required\s*pam_wheel\.so\s*use_uid" | tr -d ' '`
   if [ "${old_value}" != "authrequiredpam_wheel.souse_uid" ] ; then
      echo 限制su用户
      \cp -f ${su_files} ${su_files}.bak
      sed '1i auth required pam_wheel.so use_uid' ${su_files}.bak>${su_files}
      old_value=`head -n 1 ${su_files}  | grep -P "auth\s*required\s*pam_wheel\.so\s*use_uid" | tr -d ' '`
      if [ "${old_value}" != "authrequiredpam_wheel.souse_uid" ] ; then echo -e "操作\033[0;31m失败\033[0m";  fi
   fi


    profile=/etc/profile
    old_value=`grep -Po "^\s*TMOUT\s*=\s*\K\d+$" ${profile}`
    if [ "${old_value}" == "" ] ; then
       echo 设置自动注销时间
       echo TMOUT=600 >>${profile}
    else
       if [ "${old_value}" != "600"  ] ; then
          echo 修改自动注销时间
          \cp -f ${profile} ${profile}.bak
          sed 's/^\s*TMOUT\s*=\s*.*/TMOUT=600/' ${profile}.bak>${profile}
       fi
    fi
    old_value=`grep -Po "^\s*TMOUT\s*=\s*\K\d+$" ${profile}`
    if [ "${old_value}" == "" ] ||  [ "${old_value}" != "600"  ]  ; then echo -e "操作\033[0;31m失败\033[0m";  fi


}


function security_ssh_power()
{

   ssh_config=/etc/ssh/sshd_config
   #ssh_config=sshd_config

   old_value=`grep -Po "^\s*ClientAliveInterval\s+\K.*" ${ssh_config}`
   if [ "${old_value}" == "" ] ; then
          echo 设置空闲登出的超时间隔1
          echo ClientAliveInterval 300 >>${ssh_config}
       else
          if [ "${old_value}" != "300"  ] ; then
             echo 修改空闲登出的超时间隔1
             \cp -f ${ssh_config} ${ssh_config}.bak
             sed 's/^\s*ClientAliveInterval\s*.*/ClientAliveInterval 300/' ${ssh_config}.bak>${ssh_config}
          fi
   fi
   old_value=`grep -Po "^\s*ClientAliveInterval\s+\K.*" ${ssh_config}`
   if [ "${old_value}" == "" ] ||  [ "${old_value}" != "300" ]  ; then echo -e "操作\033[0;31m失败\033[0m";  fi


   old_value=`grep -Po "^\s*ClientAliveCountMax\s+\K.*" ${ssh_config}`
   if [ "${old_value}" == "" ] ; then
          echo 设置空闲登出的超时间隔2
          echo ClientAliveCountMax 0 >>${ssh_config}
       else
          if [ "${old_value}" != "0"  ] ; then
             echo 修改空闲登出的超时间隔2
             \cp -f ${ssh_config} ${ssh_config}.bak
             sed 's/^\s*ClientAliveCountMax\s*.*/ClientAliveCountMax 0/' ${ssh_config}.bak>${ssh_config}
          fi
   fi
   old_value=`grep -Po "^\s*ClientAliveCountMax\s+\K.*" ${ssh_config}`
   if [ "${old_value}" == "" ] ||  [ "${old_value}" != "0" ]  ; then echo -e "操作\033[0;31m失败\033[0m";  fi


   old_value=`grep -Po "^\s*IgnoreRhosts\s+\K.*" ${ssh_config}`
   if [ "${old_value}" == "" ] ; then
          echo 设置禁用.rhosts文件
          echo IgnoreRhosts  yes >>${ssh_config}
       else
          if [ "${old_value}" != "yes"  ] ; then
             echo 禁用.rhosts文件
             \cp -f ${ssh_config} ${ssh_config}.bak
             sed 's/^\s*IgnoreRhosts\s*.*/IgnoreRhosts yes/' ${ssh_config}.bak>${ssh_config}
          fi
   fi
   old_value=`grep -Po "^\s*IgnoreRhosts\s+\K.*" ${ssh_config}`
   if [ "${old_value}" == "" ] ||  [ "${old_value}" != "yes" ]  ; then echo -e "操作\033[0;31m失败\033[0m";  fi



   old_value=`grep -Po "^\s*HostbasedAuthentication\s+\K.*" ${ssh_config}`
   if [ "${old_value}" == "" ] ; then
          echo 设置禁用基于主机的认证
          echo HostbasedAuthentication  no >>${ssh_config}
       else
          if [ "${old_value}" != "no"  ] ; then
             echo 禁用基于主机的认证
             \cp -f ${ssh_config} ${ssh_config}.bak
             sed 's/^\s*HostbasedAuthentication\s*.*/HostbasedAuthentication no/' ${ssh_config}.bak>${ssh_config}
          fi
   fi
   old_value=`grep -Po "^\s*HostbasedAuthentication\s+\K.*" ${ssh_config}`
   if [ "${old_value}" == "" ] ||  [ "${old_value}" != "no" ]  ; then echo -e "操作\033[0;31m失败\033[0m";  fi




   old_value=`grep -Pio "^\s*banner\s+\K.*" ${ssh_config}`
   if [ "${old_value}" == "" ] ; then
          echo 开启SSH警告
          echo banner   /etc/issue>>${ssh_config}
   fi
   old_value=`grep -Pio "^\s*banner\s+\K.*" ${ssh_config}`
   if [ "${old_value}" == "" ] ; then echo -e "操作\033[0;31m失败\033[0m";  fi


   old_value=`grep -Po "^\s*PermitEmptyPasswords\s+\K.*" ${ssh_config}`
   if [ "${old_value}" == "" ] ; then
          echo 设置禁止SSH空密码登陆
          echo PermitEmptyPasswords  no >>${ssh_config}
       else
          if [ "${old_value}" != "no"  ] ; then
             echo 禁止SSH空密码登陆
             \cp -f ${ssh_config} ${ssh_config}.bak
             sed 's/^\s*PermitEmptyPasswords\s*.*/PermitEmptyPasswords no/' ${ssh_config}.bak>${ssh_config}
          fi
   fi
   old_value=`grep -Po "^\s*PermitEmptyPasswords\s+\K.*" ${ssh_config}`
   if [ "${old_value}" == "" ] ||  [ "${old_value}" != "no" ]  ; then echo -e "操作\033[0;31m失败\033[0m";  fi


}


function security_firewall()
{
    state=`firewall-cmd --state 2>&1`
    if [ "${state}" != "running" ] ; then
       echo 开启防火墙
       service firewalld start
    fi
    state=`firewall-cmd --state  2>&1`
    if [ "${state}" != "running" ]  ; then echo -e "操作\033[0;31m失败\033[0m";  fi


}




function security_audit()
{
#_ 防止变成数组
aa[0]="-w_/var/log/audit/_-k_LOG_audit"
aa[${#aa[@]}]="-w_/etc/audit/_-p_wa_-k_CFG_audit"
aa[${#aa[@]}]="-w_/etc/sysconfig/auditd_-p_wa_-k_CFG_auditd.conf"
aa[${#aa[@]}]="-w_/etc/libaudit.conf_-p_wa_-k_CFG_libaudit.conf"
aa[${#aa[@]}]="-w_/etc/audisp/_-p_wa_-k_CFG_audisp"
aa[${#aa[@]}]="-w_/etc/cups/_-p_wa_-k_CFG_cups"
aa[${#aa[@]}]="-w_/etc/init.d/cups_-p_wa_-k_CFG_initd_cups"
aa[${#aa[@]}]="-w_/etc/netlabel.rules_-p_wa_-k_CFG_netlabel.rules"
aa[${#aa[@]}]="-w_/etc/selinux/mls/_-p_wa_-k_CFG_MAC_policy"
aa[${#aa[@]}]="-w_/usr/share/selinux/mls/_-p_wa_-k_CFG_MAC_policy"
aa[${#aa[@]}]="-w_/etc/selinux/semanage.conf_-p_wa_-k_CFG_MAC_policy"
aa[${#aa[@]}]="-w_/usr/sbin/stunnel_-p_x"
aa[${#aa[@]}]="-w_/etc/security/rbac-self-test.conf_-p_wa_-k_CFG_RBAC_self_test"
aa[${#aa[@]}]="-w_/etc/aide.conf_-p_wa_-k_CFG_aide.conf"
aa[${#aa[@]}]="-w_/etc/cron.allow_-p_wa_-k_CFG_cron.allow"
aa[${#aa[@]}]="-w_/etc/cron.deny_-p_wa_-k_CFG_cron.deny"
aa[${#aa[@]}]="-w_/etc/cron.d/_-p_wa_-k_CFG_cron.d"
aa[${#aa[@]}]="-w_/etc/cron.daily/_-p_wa_-k_CFG_cron.daily"
aa[${#aa[@]}]="-w_/etc/cron.hourly/_-p_wa_-k_CFG_cron.hourly"
aa[${#aa[@]}]="-w_/etc/cron.monthly/_-p_wa_-k_CFG_cron.monthly"
aa[${#aa[@]}]="-w_/etc/cron.weekly/_-p_wa_-k_CFG_cron.weekly"
aa[${#aa[@]}]="-w_/etc/crontab_-p_wa_-k_CFG_crontab"
aa[${#aa[@]}]="-w_/var/spool/cron/root_-k_CFG_crontab_root"
aa[${#aa[@]}]="-w_/etc/group_-p_wa_-k_CFG_group"
aa[${#aa[@]}]="-w_/etc/passwd_-p_wa_-k_CFG_passwd"
aa[${#aa[@]}]="-w_/etc/gshadow_-k_CFG_gshadow"
aa[${#aa[@]}]="-w_/etc/shadow_-k_CFG_shadow"
aa[${#aa[@]}]="-w_/etc/security/opasswd_-k_CFG_opasswd"
aa[${#aa[@]}]="-w_/etc/login.defs_-p_wa_-k_CFG_login.defs"
aa[${#aa[@]}]="-w_/etc/securetty_-p_wa_-k_CFG_securetty"
aa[${#aa[@]}]="-w_/var/log/faillog_-p_wa_-k_LOG_faillog"
aa[${#aa[@]}]="-w_/var/log/lastlog_-p_wa_-k_LOG_lastlog"
aa[${#aa[@]}]="-w_/var/log/tallylog_-p_wa_-k_LOG_tallylog"
aa[${#aa[@]}]="-w_/etc/hosts_-p_wa_-k_CFG_hosts"
aa[${#aa[@]}]="-w_/etc/sysconfig/network-scripts/_-p_wa_-k_CFG_network"
aa[${#aa[@]}]="-w_/etc/inittab_-p_wa_-k_CFG_inittab"
aa[${#aa[@]}]="-w_/etc/rc.d/init.d/_-p_wa_-k_CFG_initscripts"
aa[${#aa[@]}]="-w_/etc/ld.so.conf_-p_wa_-k_CFG_ld.so.conf"
aa[${#aa[@]}]="-w_/etc/localtime_-p_wa_-k_CFG_localtime"
aa[${#aa[@]}]="-w_/etc/sysctl.conf_-p_wa_-k_CFG_sysctl.conf"
aa[${#aa[@]}]="-w_/etc/modprobe.conf_-p_wa_-k_CFG_modprobe.conf"
aa[${#aa[@]}]="-w_/etc/pam.d/_-p_wa_-k_CFG_pam"
aa[${#aa[@]}]="-w_/etc/security/limits.conf_-p_wa_-k_CFG_pam"
aa[${#aa[@]}]="-w_/etc/security/pam_env.conf_-p_wa_-k_CFG_pam"
aa[${#aa[@]}]="-w_/etc/security/namespace.conf_-p_wa_-k_CFG_pam"
aa[${#aa[@]}]="-w_/etc/security/namespace.init_-p_wa_-k_CFG_pam"
aa[${#aa[@]}]="-w_/etc/aliases_-p_wa_-k_CFG_aliases"
aa[${#aa[@]}]="-w_/etc/postfix/_-p_wa_-k_CFG_postfix"
aa[${#aa[@]}]="-w_/etc/ssh/sshd_config_-k_CFG_sshd_config"
aa[${#aa[@]}]="-w_/etc/vsftpd.ftpusers_-k_CFG_vsftpd.ftpusers"
aa[${#aa[@]}]="-a_exit,always_-F_arch=b32_-S_sethostname"
aa[${#aa[@]}]="-w_/etc/issue_-p_wa_-k_CFG_issue"
aa[${#aa[@]}]="-w_/etc/issue.net_-p_wa_-k_CFG_issue.net"

   changed_audit=0
   config=/etc/audit/audit.rules
   #config=audit
   for c in ${aa[@]}
   do
       cc=`echo $c | tr '_' ' '`
       #echo "$cc"
       conf_name=`echo ${cc} | grep -Po "^\-\w\s+\K\S+"`
       old_value=`grep -Po "^\s*\-\w\s*${conf_name}\s+\K.*" ${config}`
       if [ "${old_value}" == "" ] ; then
              echo 设置审计${conf_name}
              echo "${cc}" >>${config}
              changed_audit=1
       fi
       old_value=`grep -Po "^\s*\-\w\s*${conf_name}\s+\K.*" ${config}`
       if [ "${old_value}" == "" ]   ; then echo -e "操作\033[0;31m失败\033[0m";  fi
   done

   if [ "${changed_audit}" == "1" ]; then
      \cp -f ${config}  ${config}.bak
      grep -Pv "^\s*$" ${config}.bak>${config}
      service auditd restart
   fi
   
}

init_display
runner_root
#check_security
security_root_power
security_ssh_power
security_firewall
security_audit